/*

Archivo: "abstractor.h"

Implementación de un "abstractor" para el conjunto.
Permite la instanciación de un conjunto con elementos de
un tipo dado y con una estructura de soporte especificada,
la cuál se conecta con el patrón "bridge".

Implementación de un parser para los comandos del conjunto.

Autor: Diego Luna

Primera versión: 5-6-2012

*/


#ifndef __ABSTRACTOR_H_INCLUDED
#define __ABSTRACTOR_H_INCLUDED


#include <iostream>
#include <string>

// Decide si se compilan los métodos de prueba para los contenedores (implementaciones).
#define CONTAINER_DEBUG 0

// Permite el acceso a la representación
// interna de la lista por la tabla de hash.
// Se debe incluir "list.h" antes que "hashtable.h".
#define HASH_TABLE_NEED_ACCESS_TO_LIST 1
#define HASH_TABLE_CLASS_NAME Hash_Table_Murmur
#define HASH_TABLE_TEMPLATE_NAME Hash_Table_Murmur<T>


#include "globals.h"
#include "bases.h"
#include "tree.h"
#include "list.h"
#include "hashtable.h"
#include "set.h"


#define COMMAND_EXECUTED		0
#define COMMAND_PARSED			0
#define COMMAND_EXPECTED		1
#define UNKNOWN_COMMAND			2
#define PARAMETER_EXPECTED		3
#define PARAMETER_NOT_EXPECTED	4
#define INVALID_PARAMETER		5

// Implementaciones posibles para el conjunto.
enum t_implementations {timp_list, timp_tree, timp_hash};

// Tipos de elementos posibles para el conjunto.
enum t_datatypes {tdtype_int, tdtype_float, tdtype_string};

// Comandos del "abstractor".
enum t_commands {tcmd_error, tcmd_nop, tcmd_add, tcmd_includes, tcmd_remove, 
	tcmd_is_empty, tcmd_size, tcmd_wipe, tcmd_print};

// Tipo enumerado "bool", que tiene sobrecargado el oprador de salida.
enum bool_enum { BE_FALSE = 0, BE_TRUE = 1};


/* ========================= Set_Abstractor - Begin ========================== */
// Esta clase se abstrae de los tipos de datos contenidos en cada una las
// especializaciones de los templates, trabaja asumiendo que una vez instanciados
// el "implementor" y el "handle" con un tipo se trabajará siempre con ese tipo.

class Set_Abstractor
{
private:

    //************************
    // Atributos de SetHandle.

    // Tipo de "implementor"
	t_implementations implementation_;

	// Tipo de dato contenido.
	t_datatypes data_type_;

	// Puntero al "implementor".
	void* implementor_;

	// Puntero al "handle" (conjunto).
	void* set_;

    //************************

public:

    // ++++++++++++++++++++++++ Constructores\Destructores - Begin +++++++++++++++++++++++++++++

    // Constructor.
    Set_Abstractor(t_implementations, t_datatypes);

    // Constructor copia.
    Set_Abstractor(const Set_Abstractor&);

    // Destructor.
    ~Set_Abstractor();

    // ++++++++++++++++++++++++ Constructores\Destructores - End +++++++++++++++++++++++++++++++


    // ++++++++++++++++++++++++ Métodos públicos - Begin +++++++++++++++++++++++++++++++++++++++

	// Recibe un comando y su parámetro y devuelve un código de error y por referencia el
	// string resultado.
	byte execute(const t_commands, const std::string &, std::ostream&);

    // Devuelve un string que identifica a la clase del contenedor.
    std::string class_ID() const;

    // ++++++++++++++++++++++++ Métodos públicos - End +++++++++++++++++++++++++++++++++++++++++


    // ++++++++++++++++++++++++ Operadores - Begin ++++++++++++++++++++++++++++++++++++++++++++++

    // Operador de asignación.
    Set_Abstractor& operator=(const Set_Abstractor&);

    // Operador de comparación por igualdad.
    bool operator==(const Set_Abstractor&);

    // Operador de comparación por igualdad.
    bool operator!=(const Set_Abstractor&);

    // ++++++++++++++++++++++++ Operadores - End ++++++++++++++++++++++++++++++++++++++++++++++++
	
private:

	// ++++++++++++++++++++++++ Métodos privados - Begin +++++++++++++++++++++++++++++++++++++++

	// Executa un comando especificado imprimiendo el resultado..
	void execute(const t_commands, const void*, std::ostream&);

	// Construye el "handle" y el "implementor".
	void create_implementation();

	// Detruye el "handle" y el "implementor".
	void destroy_implementation();

    // Agrega un elemento al contenedor.
    bool_enum add(const void*);

    // Elimina un elemento del contenedor (si se encuentra).
    bool_enum remove(const void*);

    // Determina si un elemento se encuentra en el contenedor.
    bool_enum includes(const void*) const;

    // Vacía el contenedor.
    void wipe();

    // Determina si el contenedor esta vacío.
    bool is_empty() const;

    // Devuelve la cantidad de elementos en el contenedor.
    size_t size() const;

    // Imprime los elementos contenidos.
    void print(std::ostream&) const;


	// Crea una especialización del template "implementor" árbol con el tipo dado.
	void* create_tree_implementor(t_datatypes);

	// Crea una especialización del template "implementor" lista con el tipo dado.
	void* create_list_implementor(t_datatypes);

	// Crea una especialización del template "implementor" tabla de hash con el tipo dado.
	void* create_hashtable_implementor(t_datatypes);

	// Crea una especialización del template "handle" con el tipo dado.
	void* create_set_handle(t_datatypes, void*);

	// ++++++++++++++++++++++++ Métodos privados - End +++++++++++++++++++++++++++++++++++++++++
	
};

/* ========================= Set_Abstractor - End ========================== */


/* ========================= Set_Command_Parser - Begin ========================== */
// Esta clase parsea strings de comandos y sus parámetros, devolviendo un dato
// de tipo enumerado que corresponde a un comando a ejecutar y un string que
// representa el parámetro correspondiente (El set convertirá este al
// tipo adecuado según los elementos que contenga).

class Set_Command_Parser
{

public:

    // ++++++++++++++++++++++++ Constructores\Destructores - Begin +++++++++++++++++++++++++++++
	// Constructor.
	Set_Command_Parser();

	// Destructor.
	~Set_Command_Parser();
    // ++++++++++++++++++++++++ Constructores\Destructores - End +++++++++++++++++++++++++++++++


    // ++++++++++++++++++++++++ Métodos públicos - Begin +++++++++++++++++++++++++++++++++++++++

	// Parsea el string dado, devuelve código de error.
	byte parse(const std::string &, t_commands&, std::string &);

    // ++++++++++++++++++++++++ Métodos públicos - End +++++++++++++++++++++++++++++++++++++++++

};

/* ========================= Set_Command_Parser - End ============================ */


// ++++++++++++++++++++++++ Public Functions - Begin ++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Devuelve la descripción de los errores devueltos por el
// "Set_Abstractor" y el "Set_Command_Parser".
std::string get_error_description(byte);

// ++++++++++++++++++++++++ Public Functions - End ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


#endif
